using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Drawing;

namespace SimplIDE
{
  class CodeEditor : RichTextBox
  {
    public CodeEditor()
    {
      Dock = DockStyle.Fill;
      WordWrap = false;
      Font = new System.Drawing.Font("Courier New", 10.0f);
      FileInfo fi = new FileInfo(Application.ExecutablePath);
      syntaxHighlighter = SyntaxHighlighter.Load(fi.DirectoryName + @"\SyntaxHighlighterSettingsBlack.xml");
      BackColor = syntaxHighlighter.Colors.Background;
      ForeColor = syntaxHighlighter.Colors.Text;
      //DebugAddSampleCode();
    }

    // debug
    void DebugAddSampleCode()
    {
      string s = string.Empty;
      s += "// test" + Environment.NewLine;
      s += Environment.NewLine;
      s += "/*" + Environment.NewLine;
      s += " * external entry point" + Environment.NewLine;
      s += " */" + Environment.NewLine;
      s += Environment.NewLine;
      s += "int main(int argc, char** argv)" + Environment.NewLine;
      s += "{" + Environment.NewLine;
      s += "  // standard cpp test :)" + Environment.NewLine;
      s += "  printf(\"Hello, World!\");" + Environment.NewLine;
      s += "  return 0;" + Environment.NewLine;
      s += "}" + Environment.NewLine;
      paintDisabled = true;
      Text = s;
      syntaxHighlighter.Colorize(this, 0, Text.Length);
      paintDisabled = false;
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Enter)
      {
        paintDisabled = true;
        syntaxHighlighter.Ident(this);
        paintDisabled = false;
      }
      base.OnKeyUp(e);
    }

    // lazy recolor
    int prevCursorPos = 0;
    int prevTextLength = -1;
 		protected override void OnTextChanged(EventArgs e)
    {
      if (paintDisabled)
        return;
      paintDisabled = true;
      int pos = Math.Min(SelectionStart, prevCursorPos);
      int len = Math.Max(SelectionStart, prevCursorPos) - pos;
      prevTextLength = -1;
      //System.Diagnostics.Debug.WriteLine(string.Format("pos:{0}, length:{1} (prevpos:{2}, start:{3})", pos, len, prevCursorPos, SelectionStart));
      syntaxHighlighter.Colorize(this, pos, len);
      paintDisabled = false;
      base.OnTextChanged(e);
      prevCursorPos = SelectionStart;
    }

    protected override void OnSelectionChanged(EventArgs e)
    {
      if (paintDisabled)
        return;
      if (prevTextLength <= 0 || prevTextLength == Text.Length)
      {
        prevCursorPos = SelectionStart;
        //System.Diagnostics.Debug.WriteLine(string.Format("selection start:{0}, length:{1}", SelectionStart, SelectionLength));
      }
      prevTextLength = Text.Length;
      base.OnSelectionChanged(e);
    }

    // prevent flickering on keypress
    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
      if (m.Msg == 0x00f)
      {
        if (!paintDisabled && !firstTimeDraw)
        {
          base.WndProc(ref m);
        }
        else
        {
          if (firstTimeDraw)
          {
            firstTimeDraw = false;
            paintDisabled = true;
            syntaxHighlighter.Colorize(this, 0, Text.Length);
            paintDisabled = false;
            Modified = false;
          }
          m.Result = IntPtr.Zero;
        }
      }
      else
        base.WndProc(ref m);
    }

    SyntaxHighlighter syntaxHighlighter = null;
    bool paintDisabled = false;
    bool firstTimeDraw = true;
  }
}
